import okhttp3.OkHttpClient;
import okhttp3.Request;
import okhttp3.Response;
import rx.Observable;
import rx.Observer;
import rx.functions.Action0;
import rx.schedulers.Schedulers;

import javax.crypto.Cipher;
import javax.crypto.KeyGenerator;
import java.io.IOException;
import java.security.Key;
import java.util.ArrayList;

public class Main {

  public static void println(String msg) {
    System.out.println(msg == null ? "null" : msg);
  }

  public static class Person {
    {
      println("Person 类中局部代码块");
    }
  }

  public static class Student extends Person {
    long id;
    String name;
    char gender;

    {
      println("类中局部代码块");
    }

    public Student() {
      println("Construct");
    }
  }

  // for all cached media
  public static String mytest(String url) {
    if (url == null || !url.toLowerCase().startsWith("http")) return url;

    int length = url.length();
    boolean hasDoubleSlash = false;
    for (int i = 0; i < length; i++) {
      if (url.charAt(i) == '/') {
        if (!hasDoubleSlash) {
          i += 1;
          hasDoubleSlash = true;
        } else {
          return url.substring(i);
        }
      }
    }
    return url;
  }

//  public static void main(String[] args) throws IOException {
//		Student stu = new Student();
//		stu.id = 100L;
//		stu.name = "mytest";
//		stu.gender = 'm';
//		Gson gson = new Gson();
//		System.out.println(gson.toJson(stu));
//
//		String url = "http://apis.juhe.cn/simpleWeather/query?city=%E8%8B%8F%E5%B7%9E&key=123";
//		// OkHttpClient.Builder httpBuilder = new OkHttpClient.Builder();
//		// final OkHttpClient client = httpBuilder.build();
//		// String test = run(url, client);
//		// WeatherResult result = gson.fromJson(test, WeatherResult.class);
//		// println(result.toString());
//		println(mytest(url));

//		println(excludeBraces("{这}里测试{dfdf}哦"));

  //  }
  private String algorithm; // 算法，如DES

  private Key key; // 根据算法生成的密钥

  private String plainText; // 明文


  KeyGenerator keyGenerator;

  Cipher cipher;


  // 函数进行初始化

  Main(String alg, String msg) {

    algorithm = alg;

    plainText = msg;

  }


  // 加密函数，将原文加密成密文

  public byte[] CipherMsg() {

    byte[] cipherText = null;


    try {

      // 生成Cipher对象

      cipher = Cipher.getInstance(algorithm);

      // 用密钥加密明文(plainText),生成密文(cipherText)

      cipher.init(Cipher.ENCRYPT_MODE, key); // 操作模式为加密(Cipher.ENCRYPT_MODE),key为密钥

      cipherText = cipher.doFinal(plainText.getBytes());// 得到加密后的字节数组

      //String str = new String(cipherText);

    } catch (Exception e) {

      e.printStackTrace();

    }

    return cipherText;

  }


  // 解密函数，将密文解密回原文

  public String EncipherMsg(byte[] cipherText, Key k) {

    byte[] sourceText = null;


    try {

      cipher.init(Cipher.DECRYPT_MODE, k); // 操作模式为解密,key为密钥

      sourceText = cipher.doFinal(cipherText);

    } catch (Exception e) {

      e.printStackTrace();

    }

    return new String(sourceText);


  }


  // 生成密钥

  public Key initKey() {

    try {

      // 初始化密钥key

      keyGenerator = KeyGenerator.getInstance(algorithm);

      keyGenerator.init(56);// 选择DES算法,密钥长度必须为56位

      key = keyGenerator.generateKey();// 生成密钥，每次生成的密钥都是不一样的

    } catch (Exception ex) {

      ex.printStackTrace();

    }

    return key;

  }


  // 获取Key类型的密钥

  public Key getKey() {

    return key;

  }


  // 获取Key类型的密钥

  public Key getKey(byte[] k) {

    try {

      cipher.init(Cipher.UNWRAP_MODE, key);

      key = cipher.unwrap(k, algorithm, Cipher.DECRYPT_MODE);

    } catch (Exception ex) {

      ex.printStackTrace();

    }

    return key;

  }


  // 获取密钥包装成byte[]类型的

  public byte[] getBinaryKey(Key k) {

    byte[] bk = null;

    try {

      cipher.init(Cipher.WRAP_MODE, k);

      bk = cipher.wrap(k);

    } catch (Exception ex) {

      ex.printStackTrace();

    }

    return bk;

  }


  public static void main(String[] args) {

//    String algorithm = "DES"; // 定义加密算法,可用DES,DESede,Blowfish
//
//    String message = "hello world"; // 生成个DES密钥
////
//    Key key;
//
//
//    Main cm = new Main(algorithm, message);
//
//    key = cm.initKey();
//
//
//    byte[] msg = cm.CipherMsg();
//
//
//
//    System.out.println("加密后的密文为：" + new String(msg));
//
//    System.out.println("密钥key为 :" + key.toString());
//
//    System.out.println("密钥BinaryKey为 :" + cm.getBinaryKey(key));
//
//    System.out.println("解密密文为：" + cm.EncipherMsg(msg, key));

//    String text = "观看直播有机会和主播配对恭喜你获得内测开";
//    StringBuilder sb = new StringBuilder();
//    for (int i = 0; i < text.length(); i++) {
//      if (i != 0 && i % 12 == 0) {
//        sb.append('\n');
//      }
//      sb.append(text.charAt(i));
//    }
//    System.out.println(sb.toString());


    testRxDoOnSubscriber();
//    rx2Learn();
//    testRxDoOnSubscriber();
//    testRxScheduler();
  }

  private static String TAG = "mytest";

  private static void testRxDoOnSubscriber() {

    createObs().subscribeOn(Schedulers.io()).doOnSubscribe(new Action0() {
      @Override
      public void call() {
//        Log.d(TAG, "doOnSubscribe Thread:" + Thread.currentThread().getName());
      }
    }).subscribeOn(Schedulers.computation()).subscribe(new Observer<String>() {
      @Override
      public void onCompleted() {

      }

      @Override
      public void onError(Throwable e) {

      }

      @Override
      public void onNext(String s) {
        Log.d(TAG, "onNext Thread:" + Thread.currentThread().getName());

      }
    });
  }

  private static Observable<String> createObs() {
    ArrayList<String> lists = new ArrayList<>();
    lists.add("测试1");
    lists.add("测试2");
    lists.add("测试3");
    String[] arrays = new String[lists.size()];
    int i = 0;
    for (String str : lists) {
      arrays[i++] = str;
    }
    return Observable.from(arrays);
  }

//  private static void rx2Learn() {
//    //1、观察者创建一个Observer
//    Observer<String> observer = new Observer<String>() {
//      @Override
//      public void onSubscribe(@NonNull Disposable d) {
//        Log.d(TAG, "onSubscribe");
//        Log.d(TAG, "onSubscribe is :" + " Thread: " +Thread.currentThread().getName());
//      }
//
//      @Override
//      public void onNext(@NonNull String s) {
//        Log.d(TAG, "onNext data is :" + s + " Thread: " +Thread.currentThread().getName());
//      }
//
//      @Override
//      public void onError(@NonNull Throwable e) {
//        Log.d(TAG, "onError data is :" + e.toString());
//      }
//
//      @Override
//      public void onComplete() {
//        Log.d(TAG, "onComplete");
//      }
//    };
//
//    Observable<String> observable = Observable.create(new ObservableOnSubscribe<String>() {
//      @Override
//      public void subscribe(@NonNull ObservableEmitter e) throws Exception {
//        Log.d(TAG, "ObservableOnSubscribe Thread:" + Thread.currentThread().getName());
//        e.onNext("hello");
//        e.onNext("world");
//        e.onComplete();
//      }
//    });
//    observable.doOnSubscribe(new Consumer<Disposable>() {
//      @Override
//      public void accept(Disposable disposable) throws Exception {
//        Log.d(TAG, "doOnSubscribe Thread:" + Thread.currentThread().getName());
//
//      }
//    }).observeOn(Schedulers.computation()).subscribe(observer);
//  }
//
//  private static void testRxDoOnSubscriber() {
//    Observable<String> obs = createObs();
//    Observable.create(new ObservableOnSubscribe<String>() {
//      @Override
//      public void subscribe(ObservableEmitter<String> e) throws Exception {
//        System.out.println("ObservableOnSubscribe" + Thread.currentThread().getName());
//        e.onNext("test1");
//        e.onNext("test2");
//        e.onNext("test3");
//        e.onComplete();
//      }
//    }).subscribeOn(Schedulers.io()).doOnSubscribe(new Consumer<Disposable>() {
//      @Override
//      public void accept(Disposable disposable) throws Exception {
//        System.out.println("doOnSubscribe" + Thread.currentThread().getName());
//      }
//    }).subscribeOn(Schedulers.computation()).subscribe(new Observer<String>() {
//      @Override
//      public void onSubscribe(Disposable d) {
//        System.out.println("onSubscribe" + Thread.currentThread().getName());
//      }
//
//      @Override
//      public void onNext(String s) {
//        System.out.println("onNext" + Thread.currentThread().getName());
//      }
//
//      @Override
//      public void onError(Throwable e) {
//
//      }
//
//      @Override
//      public void onComplete() {
//
//      }
//    });
//  }
//
//  private static Observable<String> createObs() {
//    ArrayList<String> lists = new ArrayList<>();
//    lists.add("测试1");
//    lists.add("测试2");
//    lists.add("测试3");
//    String[] arrays = new String[lists.size()];
//    int i = 0;
//    for (String str : lists) {
//      arrays[i++] = str;
//    }
//    return Observable.fromArray(arrays);
//  }
//
//  private static void testRxScheduler() {
////    Observable.create(new ObservableOnSubscribe<String>() {
////      @Override
////      public void subscribe(ObservableEmitter<String> e) throws Exception {
////        System.out.println("create thread:" + Thread.currentThread().getName());
////        e.onNext("测试1");
////        e.onNext("测试2");
////        e.onNext("测试3");
////        e.onComplete();
////      }
////    })
//    createObs().subscribeOn(Schedulers.io()).lift(new ObservableOperator<String, String>() {
//      @Override
//      public Observer<? super String> apply(Observer<? super String> observer) throws Exception {
//        System.out.println("lift1 thread:" + Thread.currentThread().getName());
//        return observer;
//      }
//    }).observeOn(Schedulers.computation()).lift(new ObservableOperator<String, String>() {
//      @Override
//      public Observer<? super String> apply(Observer<? super String> observer) throws Exception {
//        System.out.println("lift2 thread:" + Thread.currentThread().getName());
//        return observer;
//      }
//    }).subscribeOn(Schedulers.newThread()).lift(new ObservableOperator<String, String>() {
//      @Override
//      public Observer<? super String> apply(Observer<? super String> observer) throws Exception {
//        System.out.println("lift3 thread:" + Thread.currentThread().getName());
//        return observer;
//      }
//    }).observeOn(Schedulers.io()).doOnSubscribe(new Consumer<Disposable>() {
//      @Override
//      public void accept(Disposable disposable) throws Exception {
//        System.out.println("doOnSubscribe thread:" + Thread.currentThread().getName());
//
//      }
//    }).subscribe(
//        new Observer<String>() {
//          @Override
//          public void onSubscribe(Disposable d) {
//            System.out.println("subscribe onSubscribe thread:" + Thread.currentThread().getName());
//          }
//
//          @Override
//          public void onNext(String s) {
//            System.out.println("subscribe onNext thread:" + Thread.currentThread().getName() + " string:" + s);
//
//          }
//
//          @Override
//          public void onError(Throwable e) {
//
//          }
//
//          @Override
//          public void onComplete() {
//            System.out.println("subscribe complete thread:" + Thread.currentThread().getName());
//
//          }
//        }
//    );
//  }


  /**
   * 若source里面有{}，则直接删除{}及其中内容
   */
  private static String excludeBraces(String source) {
    boolean hasBraces = source.contains("{");
    if (hasBraces) {
      StringBuilder sb = new StringBuilder();
      boolean inBraces = false;
      for (int i = 0; i < source.length(); i++) {
        char word = source.charAt(i);
        if (word == '{') {
          inBraces = true;
        } else if (word == '}') {
          inBraces = false;
        } else if (!inBraces) {
          sb.append(word);
        }
      }
      return sb.toString();
    }
    return source;
  }

  public static String run(String url, OkHttpClient client) throws IOException {
    Request request = new Request.Builder()
        .url(url)
        .build();
    Response response = client.newCall(request).execute();
    return response.body().string();
  }

}